home *** CD-ROM | disk | FTP | other *** search
/ C/C++ Users Group Library 1996 July / C-C++ Users Group Library July 1996.iso / vol_100 / 134_01 / cmdutil.c < prev    next >
Text File  |  1985-08-19  |  5KB  |  242 lines

  1. /*    Command utilities    */
  2.  
  3. /*    This package contains a variety of functions useful for writing
  4.     command processors, including a standard command line argument
  5.     processor.
  6.  
  7.     Kevin Kenny
  8.     729-A E. Cochise Dr.
  9.     Phoenix, Arizona   85020.
  10.  
  11.     This code is in the public domain.    */
  12.  
  13. /*    Functions included:
  14.  
  15. abbrev        Test for a valid abbreviation.
  16. initv        Initialize an integer vector.
  17. patmat        Match a name with a pattern; optionally, substitute in a
  18.         second pattern.
  19. procarg        Process an argument from command line.
  20. showsynt    Display the correct syntax for a command.
  21.  
  22. */
  23.  
  24. #include <bdscio.h>
  25. #include <cmdutil.h>
  26.  
  27. /*    ABBREV - Test for a valid abbreviation */
  28.  
  29. abbrev (text, pattern)
  30.     char * text;        /* Text to test */
  31.     char * pattern;        /* Pattern to match it against; lowercase
  32.                     letters are optional */
  33.     {
  34.     while (*pattern != '\0') {
  35.         if (islower (*pattern)) {    /* Optional character */
  36.             if (tolower (*text) == *pattern++
  37.              && abbrev (text + 1, pattern))
  38.                 return (TRUE);
  39.             }
  40.         else {                /* Required character */
  41.             if (toupper (*text++) != *pattern++)
  42.                 return (FALSE);
  43.             }
  44.         }
  45.     return (*text == '\0');
  46.     }
  47.  
  48. /*    Initv - initialize a vector    */
  49.  
  50. int * initv (vect, endval, contents)
  51.     int *vect;               /* Vector to initialize */
  52.     int endval;                /* Value flagging end of list */
  53.     int contents;            /* Stuff to put in it */
  54.     {
  55.     int *contp;
  56.  
  57.     contp = &contents;
  58.     while ((*vect++ = *contp++) != endval);
  59.     }
  60.  
  61. /*    Patmat - Name pattern matcher     */
  62.  
  63. int patmat (name, pat, equiv, newname)
  64.     char *name, *pat, *equiv, *newname;
  65.      {
  66.  
  67.     char c, mc, flag;
  68.  
  69.     mc = *pat++;            /* Get char from pat */
  70.     while (c = *name++) {        /* Corresponding char */
  71.         switch (mc) {
  72.  
  73. case '?':                /* '?' matches any single char */
  74.             if (equiv) {
  75.                 if (_passtxt (&equiv, &newname)) {
  76.                     *newname++ = c;
  77.                     if (*pat != '?') ++equiv;
  78.                     }
  79.                 }
  80.             mc = *pat++;
  81.             break;
  82.  
  83. case '*':                /* '*' matches any string */
  84.             if (equiv)
  85.                 flag = _passtxt (&equiv, &newname);
  86.             else
  87.                 flag = 0;
  88.             if (patmat (name-1, pat, equiv+flag, newname))
  89.                 return (TRUE);
  90.             if (flag) *newname++ = c; 
  91.             break;
  92.  
  93. default:                /* Anything else matches only itself */
  94.             if (toupper (mc) != toupper (c))
  95.                 return (FALSE);
  96.             mc = *pat++;
  97.             break;
  98.             }
  99.         }
  100.  
  101.     if ((mc != '*' || *pat) && mc) return (FALSE);
  102.     if (equiv) {
  103.         while (_passtxt (&equiv, &newname)) ++equiv;
  104.         *newname = '\0';
  105.         }
  106.     return (TRUE);
  107.     }
  108.  
  109. char _passtxt (insp, otsp)
  110.     char **insp, **otsp;
  111.     {
  112.  
  113.     char c;
  114.  
  115.     while ((c = **insp) && c != '*') {    
  116.         *(*otsp)++ = c;
  117.         ++*insp;
  118.         }
  119.     return (c != 0);
  120.     }
  121.  
  122. /*    Process an argument from command line    */
  123.  
  124. int procarg (argc, argv, optable, info) 
  125.     int * argc;            /* Argument count */
  126.     char * * * argv;        /* Argument vector */
  127.     struct option * optable;    /* Option list */
  128.     char * * * info;        /* Returned information */
  129.     {
  130.     int optno;        /* Option number */
  131.         char * argtext;        /* Argument text */
  132.     int parmno;        /* Parameter counter for multi-value
  133.                    options. */
  134.     
  135.     argtext = *(*argv)++;        /* Pick up an argument */
  136.     --*argc;
  137.  
  138.     if (!_isopt (argtext)) {
  139.         *info = argtext;    /* String, not an option */
  140.         return (-1);
  141.         }
  142.  
  143.     for (optno = 0; optable -> opt_text != EOF; ++optno, ++optable)
  144.         if (abbrev (argtext + 1, optable -> opt_text)) break;
  145.                 /* Search for optable entry */
  146.  
  147.     if (optable -> opt_text == EOF) {
  148.         fprintf (STD_ERR, "\n-%s: unknown option.", argtext);
  149.         *info = argtext;
  150.         return (-2);        /* Unrecognized option */
  151.         }
  152.  
  153.     switch (optable -> opt_type) {
  154.         case NAKED_KWD:
  155.         *info = 0;
  156.         return (optno);
  157.         case NVAL_KWD:
  158.         case SVAL_KWD:
  159.         if (*argc == 0 || _isopt (**argv)) {
  160.             fprintf (STD_ERR, "\n-%s option requires a value.", 
  161.                 optable -> opt_text);
  162.             *info = argtext;
  163.             return (-2);
  164.             }
  165.         break;
  166.         case MNVL_KWD:
  167.         case MSVL_KWD:
  168.         break;
  169.         default:
  170.         fprintf (STD_ERR, "\nBug: optable badly constructed.");
  171.         exit ();
  172.         }
  173.  
  174.     switch (optable -> opt_type) {
  175.         case SVAL_KWD:
  176.         *info = *(*argv)++;    /* Pick up next arg string */
  177.         --*argc;
  178.             return (optno);
  179.         case NVAL_KWD:
  180.         *info = atoi (*(*argv)++);
  181.         --*argc;
  182.         return (optno);
  183.         default:
  184.         *info = sbrk (*argc + *argc + 2);
  185.         break;
  186.         }
  187.  
  188.     for (parmno = 0; 
  189.         *argc && !_isopt (argtext = **argv);
  190.         --*argc, ++*argv, ++parmno) {
  191.  
  192.         if (optable -> opt_type == MSVL_KWD) {
  193.             (*info) [parmno + 1] = argtext;
  194.             }
  195.         else {
  196.             (*info) [parmno + 1] = atoi (argtext);
  197.             }
  198.         }
  199.     (*info) [0] = parmno;
  200.     return (optno);
  201.     }
  202.  
  203. /* Test if a string is a command option */
  204.  
  205. int _isopt (s)
  206.     char * s;
  207.     {
  208.     return (*s++ == '-' && isalpha (*s));
  209.     }
  210.  
  211. /* Display command syntax */
  212.  
  213. showsyntax (command, optable)
  214.     char * command;
  215.     struct option * optable;
  216.     {
  217.     char * opstr [6];
  218.  
  219.     initv (opstr, EOF, "", "<s>", "<n>", "<s> <s>...", "<n> <n>...", EOF);
  220.  
  221.     fprintf (STD_ERR, "\nSyntax: %s", command);
  222.  
  223.     if (optable -> opt_text == EOF) return;
  224.  
  225.     fprintf (STD_ERR, " <options>\nOptions:");
  226.  
  227.     while (optable -> opt_text != EOF) {
  228.  
  229.         fprintf (STD_ERR, "\n\t-%s %s", optable -> opt_text,
  230.             opstr [optable -> opt_type]);
  231.         ++optable;
  232.  
  233.         }
  234.     }
  235. 
  236.         return (optno);
  237.         default:
  238.         *info = sbrk (*argc + *argc + 2);
  239.         break;
  240.         }
  241.  
  242.     for (parmno = 0;